package com.brillilab.service.core.method.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.brillilab.common.entity.PageVo;
import com.brillilab.dao.mapper.method.MethodRecommendAuditMapper;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.method.RecommendAuditStateEnum;
import com.brillilab.domain.po.method.Method;
import com.brillilab.domain.po.method.MethodRecommendAudit;
import com.brillilab.domain.vo.method.MethodAuditInfoVo;
import com.brillilab.domain.vo.method.MethodAuditListVo;
import com.brillilab.domain.vo.method.MethodAuditStateVo;
import com.brillilab.service.core.method.IMethodRecommendAuditService;
import com.brillilab.service.core.method.IMethodRecommendService;
import com.brillilab.service.core.method.IMethodService;
import com.brillilab.service.logic.method.MethodRecommendLogic;
import com.brillilab.service.module.message.producer.MessageProducer;
import com.brillilab.service.module.message.template.impl.method.RecommendMethodAuditUnPassTemp;
import com.github.pagehelper.PageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author wuzhiyu
 * @Title: MethodRecommendAuditServiceImpl
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2019/2/2216:30
 */
@Service
@Transactional
public class MethodRecommendAuditServiceImpl implements IMethodRecommendAuditService {
	@Resource
	private MethodRecommendLogic methodRecommendLogic;
	@Resource
	private MethodRecommendAuditMapper methodRecommendAuditMapper;
	@Resource
	private IMethodRecommendService methodRecommendService;

	@Resource
	private IMethodService methodService;
	@Resource
	private MessageProducer messageProducer;

	/*********************************
	 * wuzhiyu
	 **************************************/
	@Override
	public MethodRecommendAudit getById(Long labMemberId, Long auditId) {
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.eq(MethodRecommendAudit::getId, auditId);
		query.eq(MethodRecommendAudit::getRecommenderId, labMemberId);
		return methodRecommendAuditMapper.selectOne(query);
	}

	@Override
	public boolean add(MethodRecommendAudit audit) {
		return methodRecommendAuditMapper.insert(audit) > 0;
	}

	@Override
	public PageVo<MethodRecommendAudit> listPagedByRecommendMemberId(Long labMemberId, Integer pageIndex,
			Integer rows,Integer state) {
		PageHelper.startPage(pageIndex, rows);
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.orderByDesc(MethodRecommendAudit::getCreateTime);
		query.eq(MethodRecommendAudit::getRecommenderId,labMemberId);
		if(state!=null){
			query.eq(MethodRecommendAudit::getState,state);
		}
		List<MethodRecommendAudit> shareList = methodRecommendAuditMapper.selectList(query);
		PageVo<MethodRecommendAudit> vo = new PageVo<MethodRecommendAudit>(shareList);
		return new PageVo<MethodRecommendAudit>(vo.getPageNum(), vo.getPageSize(), vo.getTotalRow(), shareList);
	}

	@Override
	public boolean saveList(List<MethodRecommendAudit> list) {
		return methodRecommendAuditMapper.saveList(list)>0;
	}

	@Override
	public MethodRecommendAudit getByRecommendMethodId(Long labId,Long methodRecommendId) {
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.eq(MethodRecommendAudit::getRecommendMethodId,methodRecommendId);
		query.eq(MethodRecommendAudit::getLabId,labId);
		return methodRecommendAuditMapper.selectOne(query);
	}

	@Override
	public boolean deleteNotAudit(Long methodId) {
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.eq(MethodRecommendAudit::getMethodId,methodId);
		query.eq(MethodRecommendAudit::getState,RecommendAuditStateEnum.AuditWait.getState());
		return methodRecommendAuditMapper.delete(query)>0;
	}

	@Override
	public List<MethodRecommendAudit> getIsRecommendMethodAuditList(List<Long> recommendMethodIdList) {
		if(!CollectionUtils.isEmpty(recommendMethodIdList)) {
			LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
			query.in(MethodRecommendAudit::getRecommendMethodId, recommendMethodIdList);
			return methodRecommendAuditMapper.selectList(query);
		}
		return new ArrayList<>();
	}

	@Override
	public MethodRecommendAudit getRecommendAuditByMethodId(Long methodId,Long labId) {
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.eq(MethodRecommendAudit::getMethodId,methodId);
		query.eq(MethodRecommendAudit::getLabId,labId);
		List<MethodRecommendAudit> audits=methodRecommendAuditMapper.selectList(query);
		return CollectionUtils.isEmpty(audits)?null:audits.get(0);
	}

	/*********************************
	 * 黎剑
	 *******************************************/

	@Override
	public MethodRecommendAudit selectById(Long id) {
		MethodRecommendAudit audit = methodRecommendAuditMapper.selectById(id);
		Assert.notNull(audit, "推荐方法审核记录不存在");
		return audit;
	}

	@Override
	public PageVo<MethodAuditListVo> getAuditList(Long labId, List<Long> firstTypeIds, Integer state, int pageNum, int pageSize) {
		PageHelper.startPage(pageNum, pageSize);
		List<MethodAuditListVo> auditList = methodRecommendAuditMapper.getAuditList(labId, firstTypeIds, state);
		return new PageVo<MethodAuditListVo>(auditList);
	}

	@Override
	public void operation(Long id, Integer operation) {
		Assert.isTrue(id != null && operation != null && (operation == 0 || operation == 1), "参数错误");
		MethodRecommendAudit audit = this.selectById(id);
		Assert.notNull(audit, "推荐方法审核记录不存在");
		// 0-取消推荐，1-重新推荐
		if (operation == 0) {
			Assert.isTrue(RecommendAuditStateEnum.Recommend.getState().equals(audit.getState()), "该推荐方法审核状态不是推荐状态");
			audit.setState(RecommendAuditStateEnum.RecommendCancel.getState());
			int i = methodRecommendAuditMapper.updateById(audit);
			Assert.isTrue(i == 1, "取消推荐失败");
			methodRecommendService.update(audit.getMethodId(), audit.getLabId(), BoolEnum.FALSE.getValue());
		} else if (operation == 1) {
			Assert.isTrue(RecommendAuditStateEnum.RecommendCancel.getState().equals(audit.getState()),
					"该推荐方法审核状态不是已取消状态");	
			audit.setAuditTime(new Date());
			audit.setCreateTime(new Date());
			audit.setState(RecommendAuditStateEnum.Recommend.getState());
			int i = methodRecommendAuditMapper.updateById(audit);
			Assert.isTrue(i == 1, "重新推荐失败");
			methodRecommendService.update(audit.getMethodId(), audit.getLabId(), BoolEnum.TRUE.getValue());
		}
	}

	@Override
	public MethodAuditInfoVo auditInfo(Long id) {
		return methodRecommendAuditMapper.auditInfo(id);
	}

	@Override
	public MethodAuditStateVo auditState(Long id) {
		MethodAuditInfoVo auditInfo = methodRecommendAuditMapper.auditInfo(id);
		Assert.notNull(auditInfo, "推荐方法审核记录不存在");
		MethodAuditStateVo vo = new MethodAuditStateVo();
		vo.setId(auditInfo.getId());
		vo.setState(auditInfo.getState());
		if (RecommendAuditStateEnum.AuditRefuse.getState().equals(auditInfo.getState())) {
			String formatStr = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(auditInfo.getAuditTime());
			vo.setMessage("当前方法已经被" + auditInfo.getAuditorName() + "于" + formatStr + "拒绝。");
		} else if (RecommendAuditStateEnum.Recommend.getState().equals(auditInfo.getState())
				|| RecommendAuditStateEnum.RecommendCancel.getState().equals(auditInfo.getState())) {
			String formatStr = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(auditInfo.getAuditTime());
			vo.setMessage("当前方法已经被" + auditInfo.getAuditorName() + "于" + formatStr + "审核通过。");
		}
		return vo;
	}

	@Override
	public void notAdopt(Long labId, Long auditorId, Long id, String auditOpinion) {
		MethodRecommendAudit audit = this.selectById(id);
		Assert.isTrue(audit.getLabId().equals(labId), "非该审核记录实验室登录，无权限审核");
		 Assert.isTrue(audit.getState().equals(RecommendAuditStateEnum.AuditWait.getState()), "该方法已审核过");
		audit.setState(RecommendAuditStateEnum.AuditRefuse.getState());
		audit.setAuditorId(auditorId);
		audit.setAuditOpinion(auditOpinion);
		audit.setAuditTime(new Date());
		int i = methodRecommendAuditMapper.updateById(audit);
		Assert.isTrue(i == 1, "审核驳回失败");

		//审核不通过，执行消息推送
		Method recommendMethod = methodService.getById(audit.getMethodId());
		RecommendMethodAuditUnPassTemp recommendMethodAuditUnPassTemp = new RecommendMethodAuditUnPassTemp(audit.getLabId(),recommendMethod.getUserId(), audit.getRecommenderId(),recommendMethod.getName(),auditOpinion);
		messageProducer.sendMessagePush(recommendMethodAuditUnPassTemp);
	}

	@Override
	public int updateById(MethodRecommendAudit recommendAudit) {
		return methodRecommendAuditMapper.updateById(recommendAudit);
	}


	@Override
	public int countUntreated(Long labId) {
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.eq(MethodRecommendAudit::getLabId, labId);
		query.eq(MethodRecommendAudit::getState, RecommendAuditStateEnum.AuditWait.getState());
		return methodRecommendAuditMapper.selectCount(query);
	}

	@Override
	public Map<String, Integer> getStateCount(Long labId) {
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.eq(MethodRecommendAudit::getLabId, labId);
		query.in(MethodRecommendAudit::getState, RecommendAuditStateEnum.Recommend.getState(),RecommendAuditStateEnum.RecommendCancel.getState());
		int recommendCount = methodRecommendAuditMapper.selectCount(query);
		int untreatedCount = countUntreated(labId);

		Map<String, Integer> map = new HashMap<String, Integer>();
		map.put("auditWaitCount", untreatedCount);
		map.put("recommendCount", recommendCount);
		return map;
	}

	@Override
	public List<MethodRecommendAudit> getTopByLabIdAndState(Integer top, Long labId, Integer state) {
		return methodRecommendAuditMapper.getTopByLabIdAndState(top,labId,state);
	}

	@Override
	public List<MethodRecommendAudit> selectByIds(List<Long> auditIds) {
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.in(MethodRecommendAudit::getId, auditIds);
		return methodRecommendAuditMapper.selectList(query);
	}

	@Override
	public List<MethodRecommendAudit> getByLabIdAndState(Long labId, Integer state) {
		return methodRecommendAuditMapper.getByLabIdAndState(labId,state);
	}

	/*********************************
	 * WuMenghao
	 *******************************************/

	@Override
	public List<MethodRecommendAudit> selectByLabIdAndState(Long labId,Integer state) {
		return methodRecommendAuditMapper.selectList(
				new LambdaQueryWrapper<MethodRecommendAudit>()
						.eq(MethodRecommendAudit::getLabId,labId)
						.eq(MethodRecommendAudit::getState,state));
	}

	@Override
	public List<MethodRecommendAudit> selectByMethodIds(Long labId,List<Long> methodIds) {
		LambdaQueryWrapper<MethodRecommendAudit> query = new LambdaQueryWrapper<>();
		query.eq(MethodRecommendAudit::getLabId,labId);
		query.in(MethodRecommendAudit::getMethodId, methodIds);
		return methodRecommendAuditMapper.selectList(query);
	}

}
